<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
        深克隆对象
	</body>
    <script type="text/javascript">
        // 方法一
		// const oldObj = {
        //     a: 1,
        //     b: [ 'e', 'f', 'g' ],
        //     c: { h: { i: 2 } }
        // };
        
        // const newObj = JSON.parse(JSON.stringify(oldObj))

        // console.log(newObj)

        // 该方法缺点
        // 1.他无法实现对函数 、RegExp等特殊对象的克隆
        // 2.会抛弃对象的constructor,所有的构造函数会指向Object
        // 3.对象有循环引用,会报错


        // 构造函数
        function person(pname) {
            this.name = pname;
        }

        const Messi = new person('Messi');

        // 函数
        function say() {
            console.log('hi');
        };

        const oldObj = {
            a: say,
            b: new Array(1),
            c: new RegExp('ab+c', 'i'),
            d: Messi
        };

        const newObj = JSON.parse(JSON.stringify(oldObj));

        // 无法复制函数
        console.log(newObj.a, oldObj.a); // undefined [Function: say]
        // 稀疏数组复制错误
        console.log(newObj.b[0], oldObj.b[0]); // null undefined
        // 无法复制正则对象
        console.log(newObj.c, oldObj.c); // {} /ab+c/i
        // 构造函数指向错误
        console.log(newObj.d.constructor, oldObj.d.constructor);// [Function: Object] [Function: person]



        // 方法二

        function deepCopy(source){
            const result = {};
            Object.keys(source).forEach((key)=>{
                result[key] = typeof source[key] === 'object' ? this.deepCopy(source[key]) : source[key]
            })

            return result;
        }
        
        const deepResult = deepCopy(oldObj)

        console.log('deepResult',deepResult)
        console.log('deepResult.a',deepResult.a)//[Function: say]
        console.log('deepResult.b[0]',deepResult.b[0])//undefined
        console.log('deepResult.c',deepResult.c)//{}
        console.log('deepResult.d.constructor',deepResult.d.constructor)// [Function: Object]
        // 由于要面对不同的对象(正则、数组、Date等)要采用不同的处理方式，我们需要实现一个对象类型判断函数。

	</script>
</html>
